/*
 * Copyright (C) Michael Martin & Antonio Carrozzini (TBJD)
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

package org.tbjd.client.mediators;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.tbjd.client.beans.Project;
import org.tbjd.client.beans.Resource;
import org.tbjd.client.beans.Task;
import org.tbjd.client.constants.NotificationsConstants;
import org.tbjd.client.constants.ProjectConstants;
import org.tbjd.client.decorators.ProjectsGridDecorator;
import org.tbjd.client.decorators.ResourcePickerDecorator;
import org.tbjd.client.factories.ProjectFactory;
import org.tbjd.client.factories.ResourceFactory;
import org.tbjd.client.factories.TaskFactory;
import org.tbjd.client.helpers.ProjectStatusFilterHelper;
import org.tbjd.client.interfaces.Observer;

public class ChiefMediator extends AbstractMediator implements Observer {

	private Map<Integer, Object> map = new HashMap<Integer, Object>();

	private Project project = null;
	private List<Task> tasks = null;
	private List<Resource> resources = null;

	// TODO remove those decorators because the GUI's are now in charge of creating items
	private ResourcePickerDecorator resourceDecorator = ResourcePickerDecorator.getInstance();
	private ProjectsGridDecorator projectsGridDecorator = ProjectsGridDecorator.getInstance();

	public void decide(Object action) {
		handle(action);
	}

	public void handle(Object action) {
		this.map.clear();

		/* ************************** PROJECT *************************** */
		if (((Map<?, ?>) action).containsKey(NotificationsConstants.FETCH_PROJECTS)) {
			List<Project> projects = fetchProjects(((Map<Integer, ProjectStatusFilterHelper>) action).get(NotificationsConstants.FETCH_PROJECTS));
			this.map.put(NotificationsConstants.DECORATED_PROJECTS, projectsGridDecorator.decorate(projects));
		}

		if (((Map<?, ?>) action).containsKey(NotificationsConstants.OPEN_PROJECT)) {
			System.out.println("ChiefMediator.handle() OPEN_PROJECT");
			this.project = openProject(((Map<Integer, Integer>) action).get(NotificationsConstants.OPEN_PROJECT));
			ProjectConstants.PROJECT_BEGINDATE = this.project.getBeginDate();

			fetchTasks();
			this.map.put(NotificationsConstants.LIST_TASKS, this.tasks);
		}

		if (((Map<?, ?>) action).containsKey(NotificationsConstants.DELETE_PROJECT)) {
			deleteProject(((Map<Integer, Integer>) action).get(NotificationsConstants.DELETE_PROJECT));
		}

		if (((Map<?, ?>) action).containsKey(NotificationsConstants.TOGGLE_STAR)) {
			updateProject(NotificationsConstants.TOGGLE_STAR, ((Map<Integer, Integer>) action).get(NotificationsConstants.TOGGLE_STAR));
		}

		if (((Map<?, ?>) action).containsKey(NotificationsConstants.TOGGLE_PRIORITY)) {
			updateProject(NotificationsConstants.TOGGLE_PRIORITY, ((Map<Integer, Integer>) action).get(NotificationsConstants.TOGGLE_PRIORITY));
		}

		/* ************************** TASKS *************************** */
		if (((Map<?, ?>) action).containsKey(NotificationsConstants.FETCH_TASKS)) {
			System.out.println("ChiefMediator.handle() FETCH_TASKS");

			fetchTasks();
			this.map.put(NotificationsConstants.TASKS, this.tasks);
		}

		if (((Map<Integer, ?>) action).containsKey(NotificationsConstants.TASKMANAGER_RESULT)) {
			System.out.println("ChiefMediator.handle() TASKMANAGER_RESULT");
			this.map.put(NotificationsConstants.TASKMANAGER_RESULT, ((Map<Integer, ?>) action).get(NotificationsConstants.TASKMANAGER_RESULT));
		}

		/* ************************** RESOURCES *************************** */
		if (((Map<?, ?>) action).containsKey(NotificationsConstants.FETCH_RESOURCES)) {
			String criteria = (String) ((Map<?, ?>) action).get(NotificationsConstants.FETCH_RESOURCES);
			System.out.println("ChiefMediator.handle() FETCH_RESOURCES with criteria =" + criteria);
			fetchResources(criteria);
			this.map.put(NotificationsConstants.RESOURCEPICKERITEMS_DECORATED, this.resourceDecorator.decorateAsList(this.resources));
		}

		if (((Map<?, ?>) action).containsKey(NotificationsConstants.DROP_ADD_RESOURCEONTASK_resource)) {
			System.out.println("ChiefMediator.handle() DROP_ADD_RESOURCEONTASK_resource");
			this.map = (Map<Integer, Object>) action;
		}

		if (((Map<Integer, ?>) action).containsKey(NotificationsConstants.DROP_REMOVE_RESOURCEFROMTASK_resource)) {
			System.out.println("ChiefMediator.handle() DROP_REMOVE_RESOURCEFROMTASK_resource");
			// TODO ganttTaskItem resources changed
		}

		if (((Map<?, ?>) action).containsKey(NotificationsConstants.OPEN_RESOURCE)) {
			System.out.println("ChiefMediator.handle() OPEN_RESOURCE");
			// TODO open resource detail window (popup)
		}

		notifyObservers(this.map);
	}

	private List<Project> fetchProjects(ProjectStatusFilterHelper filters) {
		long begin = new Date().getTime();
		List<Project> projects = new ArrayList<Project>();

		// for the first application launch
		if (filters == null) {
			filters = ProjectStatusFilterHelper.getInstance();
		}

		// TODO to replace with a db query
		projects = (List<Project>) ProjectFactory.getInstances(50);

		if (filters.isSearch()) {
			projects = getMatchingProjects(filters.getSearchCriteria());
		}

		System.out.println("ChiefMediator.fetchProjects() " + (Long) (new Date().getTime() - begin) + "[ms]");
		return projects;
	}

	private List<Project> getMatchingProjects(String criteria) {
		// TODO to replace with a db query
		List<Project> projects = (List<Project>) ProjectFactory.getInstances(50);

		List<Project> matches = new ArrayList<Project>();
		for (Project project : projects) {
			if (project.getName().contains(criteria)) {
				matches.add(project);
			}
		}

		return matches;
	}

	private Project openProject(Integer projectId) {
		System.out.println("ChiefMediator.openProject(" + projectId + ")");

		// TODO to replace with a db query
		project = new Project();

		return project;
	}

	private void updateProject(Integer action, Integer projectId) {
		System.out.println("ChiefMediator.updateProject(" + projectId + ")");
		// TODO to replace with a db query
	}

	private void deleteProject(Integer projectId) {
		System.out.println("ChiefMediator.deleteProject(" + projectId + ")");
		// TODO to replace with a db query
	}

	private void fetchTasks() {
		System.out.println("ChiefMediator.fetchTasks()");
		if (this.tasks == null) {
			this.tasks = new ArrayList<Task>();

			// TODO to replace with a db query
			this.tasks = (List<Task>) TaskFactory.getFixedTasksWithResources(this.project);

		}
	}

	private void fetchResources(String criteria) {
		System.out.println("ChiefMediator.fetchResources()");
		if (this.resources == null) {
			this.resources = new ArrayList<Resource>();

			// TODO to replace with a db query
			this.resources = (List<Resource>) ResourceFactory.getInstances();
		}
	}

	public void update() {
	}

	public void delegate(Object action) {
	}

	public void update(Object sender) {
	}

}